package archive

import (
	"archive/tar"
	"context"
	"gitee.com/Luna-CY/hui-hui/internal/util/goroutine"
	"github.com/cheggaaa/pb/v3"
	"github.com/ulikunitz/xz"
	"io"
	"os"
	"path/filepath"
)

type reader struct {
	r  io.Reader
	ch chan int64
}

func (cls *reader) Read(p []byte) (n int, err error) {
	n, err = cls.r.Read(p)
	cls.ch <- int64(n)

	return
}

func (cls *reader) Close() (err error) {
	close(cls.ch)

	return
}

// DecompressXzPackageFile 解压xz文件
func DecompressXzPackageFile(_ context.Context, file *os.File, size int64, target string, callback func(total int64, current int64)) error {
	var bar = pb.Full.Start64(size)
	var r = &reader{r: bar.NewProxyReader(file), ch: make(chan int64, 100)}
	defer func() {
		bar.Finish()
		_ = r.Close()
	}()

	var xr, err = xz.NewReader(r)
	if nil != err {
		return err
	}

	goroutine.Go(func() {
		var current int64
		for n := range r.ch {
			current += n
			callback(size, current)
		}
	})

	var reader = tar.NewReader(xr)
	for hdr, err := reader.Next(); io.EOF != err; hdr, err = reader.Next() {
		if nil != err {
			return err
		}

		if err := os.MkdirAll(filepath.Join(target, filepath.Dir(hdr.Name)), 0755); nil != err {
			return err
		}

		if hdr.FileInfo().IsDir() {
			continue
		}

		f, err := os.OpenFile(filepath.Join(target, hdr.Name), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, hdr.FileInfo().Mode())
		if nil != err {
			return err
		}

		if _, err := io.Copy(f, reader); nil != err {
			return err
		}

		_ = f.Close()
	}

	return nil
}
